package com.dingup.mock.controller.home;

import com.alibaba.fastjson.JSONObject;
import com.dingup.api.Util.RedisUtils;
import com.dingup.api.base.HttpResContent;
import com.dingup.api.model.mock.home.SubjectNameDataMapInfo;
import com.dingup.mock.bean.exam.ExamSummaryInfo;
import com.dingup.mock.bean.exam.TsExamRecord;
import com.dingup.mock.bean.exam.TsMockReport;
import com.dingup.mock.bean.exam.TsMockReportData;
import com.dingup.mock.bean.home.SystemData;
import com.dingup.mock.bean.listening.TsListeningArticle;
import com.dingup.mock.bean.reading.TsReadingArticle;
import com.dingup.mock.bean.speaking.TsSpeakingQuestion;
import com.dingup.mock.bean.writing.TsWritingQuestion;
import com.dingup.mock.dao.exam.TsExamRecordsMapper;
import com.dingup.mock.dao.exam.TsMockReportsMapper;
import com.dingup.mock.dao.listening.TsListeningArticlesMapper;
import com.dingup.mock.dao.reading.TsReadingArticleDAO;
import com.dingup.mock.dao.speaking.TsSpeakingQuestionsMapper;
import com.dingup.mock.dao.writing.TsWritingQuestionsMapper;
import com.dingup.mock.enums.ExamContentTypeEnum;
import com.dingup.mock.enums.ExamTypeEnum;
import com.dingup.mock.feign.client.ClassInfoFeignClient;
import com.dingup.mock.module.SMockPdfReportGenerator;
import com.dingup.mock.module.SSystemDataCache;
import com.dingup.mock.util.ConstUtil;
import com.dingup.mock.util.MockUtil;
import com.dingup.util.GJsonUtil;
import com.google.gson.Gson;
import com.suyeer.basic.util.BHttpResUtil;
import org.apache.commons.collections4.map.LinkedMap;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

import static com.dingup.api.base.BaseUtil.*;


/**
 * 仅用来防止模考系统的首页
 * Created by yanggavin on 16/3/3.
 */
@Controller
@RequestMapping("/home")
public class HomeController{
    @Autowired
    ClassInfoFeignClient classInfoFeignClient;
    @Autowired
    private TsExamRecordsMapper tsExamRecordsMapper;
    @Autowired
    private TsListeningArticlesMapper tsListeningArticlesMapper;
    @Autowired
    private TsReadingArticleDAO tsReadingArticleDAO;
    @Autowired
    private TsSpeakingQuestionsMapper tsSpeakingQuestionsMapper;
    @Autowired
    private TsWritingQuestionsMapper tsWritingQuestionsMapper;
    @Autowired
    private TsMockReportsMapper tsMockReportsMapper;
   
    /**
     * 获取用户记录
     *
     * @param typeEnum
     * @param request
     * @param response
     */
    @RequestMapping(value = "/get_user_records.do", method = RequestMethod.POST)
    public void getUserRecords(@RequestParam(ConstUtil.REQUEST_PARAMETER_EXAM_CONTENT_TYPE) ExamContentTypeEnum typeEnum,
                               HttpServletRequest request,
                               HttpServletResponse response) {
        HttpResContent<List<JSONObject>> hrc = new HttpResContent<>(request, response);
        hrc.setFuncDes("获取用户记录");
        try {
            // check.
            //checkUserLoginStatus(hrc);
            // do
            String userId = RedisUtils.getInstance().getUserId(request);
            List<String> userIdList = classInfoFeignClient.getClassStudentIds(userId);
            if (CollectionUtils.isEmpty(userIdList)){
                userIdList = new ArrayList<>();
            }
            userIdList.add(userId);
            HashMap<String, Object> param = new HashMap<>();
            param.put("userIdList", userIdList);
            param.put("typeEnum", typeEnum);
            List<JSONObject> tsExamRecords = tsExamRecordsMapper.getListByUserIdList(param);
            LinkedMap<String, JSONObject> linkedMap = new LinkedMap<>();
            for (JSONObject obj : tsExamRecords) {
                String examId = obj.getString("examId");
                if (!linkedMap.containsKey(examId)) {
                    linkedMap.put(examId, obj);
                }
                if (obj.containsKey("markType")) {
                    linkedMap.get(examId).put(obj.getString("markType") + "Score", obj.getString("score"));
                }
            }
            // response.
            saveSuccessMsgAndData(hrc, new ArrayList<>(linkedMap.values()));
        } catch (Exception e) {
            e.printStackTrace();
            saveErrorMsgAndData(hrc, e);
        } finally {
             BHttpResUtil.writeResult(hrc);
        }
    }
//
    /**
     * 根据id获取详细记录
     *
     * @param id
     * @param request
     * @param response
     */
    @RequestMapping(value = "/get_detail_records.do", method = RequestMethod.POST)
    public void getDetailRecord(@RequestParam(ConstUtil.REQUEST_PARAMETER_ID) Integer id,
                                HttpServletRequest request,
                                HttpServletResponse response) {
        HttpResContent<Map> hrc = new HttpResContent<Map>(request, response);
        hrc.setFuncDes("获取详细记录");
        try {
            // check param valid
            checkParam(ConstUtil.REQUEST_PARAMETER_USER_ID, id);
            // do
            TsExamRecord tsExamRecord = tsExamRecordsMapper.getById(id);
            ExamSummaryInfo result = new Gson().fromJson(tsExamRecord.getExamSummaryInfo(), ExamSummaryInfo.class);
            // response.
            Map<String, Object> map = new HashMap<>();
            //整套模考时,查看报告 (hsqin 2017-11-6 去掉了后面的ALL条件,整个阅读、听力都要计分)  && ExamContentTypeEnum.ALL == tsExamRecord.getExamContentType()
            if (ExamTypeEnum.MOCK == tsExamRecord.getExamType() && (ExamContentTypeEnum.ALL == tsExamRecord.getExamContentType()
                    || ExamContentTypeEnum.READING == tsExamRecord.getExamContentType()
                    || ExamContentTypeEnum.LISTENING == tsExamRecord.getExamContentType())) {
                TsMockReport mr = tsMockReportsMapper.getByExamId(tsExamRecord.getExamId());
                map.put("readingScore", -1);
                map.put("listeningScore", -1);
                map.put("speakingScore", -1);
                map.put("writingScore", -1);
                if (mr != null) {
                    TsMockReportData reportData = MockUtil.createMockReportData(mr);
                    map.put("readingScore", reportData.getReadingScore());
                    map.put("listeningScore", reportData.getListeningScore());
                    map.put("speakingScore", reportData.getSpeakingScore());
                    map.put("writingScore", reportData.getWritingScore());
                    if (!StringUtils.isEmpty(mr.getSpeakingScore()) && !StringUtils.isEmpty(mr.getWritingScore())) {
                        map.put("pdfUrl", mr.getPdfUrl() == null ? "" : mr.getPdfUrl());
                    }
                }
            }
            map.put("examInfo", result);
            saveSuccessMsgAndData(hrc, map);
        } catch (Exception e) {
            saveErrorMsgAndData(hrc, e);
        } finally {
             BHttpResUtil.writeResult(hrc);
        }
    }

    /**
     * 获取各类套题名称
     *
     * @param typeEnum
     * @param request
     * @param response
     */
    @RequestMapping(value = "/get_subject_name.do", method = RequestMethod.POST)
    public void getSubjectName(@RequestParam(ConstUtil.REQUEST_PARAMETER_EXAM_CONTENT_TYPE) ExamContentTypeEnum typeEnum,
                               HttpServletRequest request,
                               HttpServletResponse response) {
        HttpResContent<HashMap<String, List<SubjectNameDataMapInfo>>> hrc = new HttpResContent<>(request, response);
        hrc.setFuncDes("获取各类套题名称");
        try {
            // do.
            HashMap<String, List<SubjectNameDataMapInfo>> resultMap = null;
            if (SSystemDataCache.getInstance().get(typeEnum.getCode()) != null) {
                resultMap = (HashMap<String, List<SubjectNameDataMapInfo>>) SSystemDataCache.getInstance().get(typeEnum.getCode()).getValue();
            }
            if (resultMap == null) {
                resultMap = getSubjectNameMapFromSql(typeEnum);
            }
            // filter data list.
            HashMap<String, List<SubjectNameDataMapInfo>> ret = GJsonUtil.cloneObject(resultMap, HashMap.class);
            filterSubjectNameList(hrc, ret);
            // response.
            saveSuccessMsgAndData(hrc, ret);
        } catch (Exception e) {
            saveErrorMsgAndData(hrc, e);
        } finally {
             BHttpResUtil.writeResult(hrc);
        }
    }

    @RequestMapping(value = "/create_pdf_report.do", method = RequestMethod.POST)
    public void createPdfReport(@RequestParam(ConstUtil.REQUEST_PARAMETER_EXAMINATION_ID) String examId,
                                HttpServletRequest request,
                                HttpServletResponse response) {
        HttpResContent<String> hrc = new HttpResContent<>(request, response);
        hrc.setFuncDes("生成模考报告PDF文件");
        try {
            // check.
            checkParam(ConstUtil.REQUEST_PARAMETER_EXAMINATION_ID, examId);
            TsMockReport tmr = tsMockReportsMapper.getByExamId(examId);
            String pdfUrl = SMockPdfReportGenerator.getInstance().makePdfReportAndSaveToOss(tmr);
            // 保存生成的pdf链接
            tmr.setPdfUrl(pdfUrl);
            if (!tsMockReportsMapper.update(tmr)) {
                throw new Exception("保存pdf链接失败");
            }
            saveSuccessMsgAndData(hrc, pdfUrl);
        } catch (Exception e) {
            saveErrorMsgAndData(hrc, e);
        } finally {
            BHttpResUtil.writeResult(hrc);
        }
    }

    /**
     * 从数据库获取套题名称数据
     *
     * @param typeEnum
     * @return
     */
    private HashMap<String, List<SubjectNameDataMapInfo>> getSubjectNameMapFromSql(ExamContentTypeEnum typeEnum) {
        HashMap<String, List<SubjectNameDataMapInfo>> resultMap = new HashMap<>();
        switch (typeEnum) {
            case DEFAULT:
                break;
            case LISTENING: {
                resultMap = getListeningSubjectName();
                break;
            }
            case SPEAKING: {
                resultMap = getSpeakingSubjectName();
                break;
            }
            case READING: {
                resultMap = getReadingSubjectName();
                break;
            }
            case WRITING: {
                resultMap = getWritingSubjectName();
                break;
            }
            case ALL: {
                List<String> list = tsExamRecordsMapper.getAllSubjectName();
                for (String s : list) {
                    resultMap.put(s, new ArrayList<SubjectNameDataMapInfo>());
                }
            }
            default:
                break;
        }
        // save list data to cache.
        SystemData systemData = new SystemData();
        systemData.setValue(resultMap);
        systemData.setKey(typeEnum.getCode());
        systemData.setBeginTime(new Date());
        SSystemDataCache.getInstance().put(typeEnum.getCode(), systemData);
        return resultMap;
    }

    private HashMap<String, List<SubjectNameDataMapInfo>> getListeningSubjectName() {
        HashMap<String, List<SubjectNameDataMapInfo>> resultMap = new HashMap<>();
        List<TsListeningArticle> list = tsListeningArticlesMapper.getAllSubjectName();
        for (TsListeningArticle tl : list) {
            String subjectName = tl.getSubjectName();
            SubjectNameDataMapInfo subjectNameDataMapInfo = new SubjectNameDataMapInfo();
            subjectNameDataMapInfo.setId(tl.getId());
            // 对应数据库表article_num字段,根据前端需求,转换显示编号
            String[] articleNumArray = {"1", "1", "2", "2", "3", "4"};
            subjectNameDataMapInfo.setTitle(tl.getArticleType().getCode() + " " + articleNumArray[tl.getArticleNum() - 1]);
            subjectNameDataMapInfo.setArticleNum(tl.getArticleNum());
            saveSubjectNameToResultMap(subjectName, subjectNameDataMapInfo, resultMap);
        }
        return resultMap;
    }

    private HashMap<String, List<SubjectNameDataMapInfo>> getSpeakingSubjectName() {
        HashMap<String, List<SubjectNameDataMapInfo>> resultMap = new HashMap<>();
        List<TsSpeakingQuestion> list = tsSpeakingQuestionsMapper.getAllSubjectName();
        for (TsSpeakingQuestion ts : list) {
            String subjectName = ts.getSubjectName();
            SubjectNameDataMapInfo subjectNameDataMapInfo = new SubjectNameDataMapInfo();
            subjectNameDataMapInfo.setId(ts.getId());
            subjectNameDataMapInfo.setTitle("Question " + ts.getQuestionNum());
            saveSubjectNameToResultMap(subjectName, subjectNameDataMapInfo, resultMap);
        }
        return resultMap;
    }

    private HashMap<String, List<SubjectNameDataMapInfo>> getReadingSubjectName() {
        HashMap<String, List<SubjectNameDataMapInfo>> resultMap = new HashMap<>();
        List<TsReadingArticle> list = tsReadingArticleDAO.getAllSubjectName();
        for (TsReadingArticle tr : list) {
            String subjectName = tr.getSubjectName();
            SubjectNameDataMapInfo subjectNameDataMapInfo = new SubjectNameDataMapInfo();
            subjectNameDataMapInfo.setId(tr.getId());
            subjectNameDataMapInfo.setTitle("Reading Passage " + tr.getArticleNum() + " " + tr.getArticleTitle());
            subjectNameDataMapInfo.setArticleNum(tr.getArticleNum());
            saveSubjectNameToResultMap(subjectName, subjectNameDataMapInfo, resultMap);
        }
        return resultMap;
    }

    private HashMap<String, List<SubjectNameDataMapInfo>> getWritingSubjectName() {
        HashMap<String, List<SubjectNameDataMapInfo>> resultMap = new HashMap<>();
        List<TsWritingQuestion> list = tsWritingQuestionsMapper.getAllSubjectName();
        String subjectName = "";
        for (TsWritingQuestion tw : list) {
            subjectName = tw.getSubjectName();
            SubjectNameDataMapInfo subjectNameDataMapInfo = new SubjectNameDataMapInfo();
            subjectNameDataMapInfo.setId(tw.getId());
            if (tw.getQuestionNum() == 1) {
                subjectNameDataMapInfo.setTitle("Integrated Writing Task");
            } else if (tw.getQuestionNum() == 2) {
                subjectNameDataMapInfo.setTitle("Independent Writing Task");
            }
            saveSubjectNameToResultMap(subjectName, subjectNameDataMapInfo, resultMap);
        }
        return resultMap;
    }

    /**
     * 保存套题名称到resultMap
     *
     * @param subjectName
     * @param subjectNameDataMapInfo
     * @param resultMap
     */
    private void saveSubjectNameToResultMap(String subjectName, SubjectNameDataMapInfo subjectNameDataMapInfo,
                                            HashMap<String, List<SubjectNameDataMapInfo>> resultMap) {
        if (!resultMap.containsKey(subjectName)) {
            resultMap.put(subjectName, new ArrayList<SubjectNameDataMapInfo>());
        }
        resultMap.get(subjectName).add(subjectNameDataMapInfo);
    }

    /**
     * 过滤模考套题名称
     * 过滤一：学生角色不能看到真题
     * 过滤二：根据权限点过滤掉单词100天对应的阅读文章
     *
     * @param resultMap
     */
    private <T> void filterSubjectNameList(HttpResContent<T> hrc, HashMap<String, List<SubjectNameDataMapInfo>> resultMap) {
//        Pattern wx100Pattern = Pattern.compile("wx_\\d{8}_word_d\\d{1,3}");
//        Pattern realTestPattern = Pattern.compile("\\d{8}_real_test");
//        List<String> keys = new ArrayList<>(resultMap.keySet());
//        if (SysUserRoleEnum.STUDENT == hrc.getCurUserRole()) {
//            for (String s : keys) {
//                if (realTestPattern.matcher(s).matches()) {
//                    resultMap.remove(s);
//                }
//            }
//        }
//        List<String> userAuthIdList = new ArrayList<>(Arrays.asList(hrc.getCurUserAuthIds().split(",")));
//        if (!userAuthIdList.contains("k")) {
//            for (String s : keys) {
//                if (wx100Pattern.matcher(s).matches()) {
//                    resultMap.remove(s);
//                }
//            }
//        }
    }
}
